package com.lotea.android.andreaditlater.io;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.database.sqlite.SQLiteStatement;

import com.lotea.android.andreaditlater.data.db.DbAdapter;

public class JSONToDb {

	private DbAdapter mDbAdapter;

	public JSONToDb(Context context) {
		mDbAdapter = new DbAdapter(context);
	}

	public void parseItemsIntoDb(String json) {
		// New transaction
		mDbAdapter.open();
		mDbAdapter.beginTransaction();

		try {
			JSONObject jsonObject = new JSONObject(json);

			// We are only interested for now in 'list' item from json
			final String strData = jsonObject
					.getString(API.Methods.Get.Keys.LIST);
			JSONObject jsonList = new JSONObject(strData);

			if (jsonList.names() != null) {
				int numItems = jsonList.names().length();

				// Prepare statements for faster execution
				SQLiteStatement statement = mDbAdapter.getItemInsertStatement();
				SQLiteStatement insertRelItemTagStatement = mDbAdapter
						.getRelItemTagInsertStatement();
				SQLiteStatement insertTagStatement = mDbAdapter
						.getTagInsertStatement();
				SQLiteStatement deleteRelItemTagStatement = mDbAdapter
						.getRelItemTagDeleteStatement();

				// Insert every item and their tags
				for (int i = 0; i < numItems; i++) {
					long itemId = Long.parseLong(jsonList.names().get(i)
							.toString());

					try {
						JSONObject jsonItem = new JSONObject(jsonList
								.getString(Long.toString(itemId)));

						// bind data to the statement
						statement.bindLong(DbAdapter.Indexes.Items.ID, itemId);
						if (jsonItem.has(API.Methods.Get.Keys.STATE))
							statement
									.bindLong(
											DbAdapter.Indexes.Items.STATE,
											Long
													.parseLong(jsonItem
															.getString(API.Methods.Get.Keys.STATE)));
						if (jsonItem.has(API.Methods.Get.Keys.TITLE))
							statement
									.bindString(
											DbAdapter.Indexes.Items.TITLE,
											jsonItem
													.getString(API.Methods.Get.Keys.TITLE));
						if (jsonItem.has(API.Methods.Get.Keys.URL))
							statement
									.bindString(
											DbAdapter.Indexes.Items.URL,
											jsonItem
													.getString(API.Methods.Get.Keys.URL));
						if (jsonItem.has(API.Methods.Get.Keys.TIME_ADDED))
							statement
									.bindLong(
											DbAdapter.Indexes.Items.TIME_ADDED,
											Long
													.parseLong(jsonItem
															.getString(API.Methods.Get.Keys.TIME_ADDED)));
						if (jsonItem.has(API.Methods.Get.Keys.TIME_UPDATED))
							statement
									.bindLong(
											DbAdapter.Indexes.Items.TIME_UPDATED,
											Long
													.parseLong(jsonItem
															.getString(API.Methods.Get.Keys.TIME_UPDATED)));

						// finally, execute insert
						statement.execute();

						// -- Tags --
						// In first place, delete all tags for this item (if it
						// has tags, they may have changed; if it hasn't,
						// existent ones must be deleted -remember that the
						// server response contains only modified items)
						deleteRelItemTagStatement.bindLong(
								DbAdapter.Indexes.RelItemsTags.ID_ITEM, itemId);
						deleteRelItemTagStatement.execute();
						deleteRelItemTagStatement.clearBindings();

						// Insert tags and relations
						if (jsonItem.has(API.Methods.Get.Keys.TAGS)) {
							final String tags = jsonItem
									.getString(API.Methods.Get.Keys.TAGS);
							String[] tagArray = tags.split(",");

							for (String tag : tagArray) {
								// long tagId = mDbAdapter.insertTag(tag);

								insertTagStatement
										.bindString(
												DbAdapter.Indexes.Tags.NAME,
												tag.trim());

								// XXX: There must be a better way to do this
								// Get tag id. If not found, insert it
								long tagId = mDbAdapter.getTagIdByName(tag
										.trim());

								if (tagId == -1) {
									tagId = insertTagStatement.executeInsert();
								}

								insertTagStatement.clearBindings();

								// Insert item-tag relations
								if (tagId != -1) {
									insertRelItemTagStatement
											.bindLong(
													DbAdapter.Indexes.RelItemsTags.ID_ITEM,
													itemId);
									insertRelItemTagStatement
											.bindLong(
													DbAdapter.Indexes.RelItemsTags.ID_TAG,
													tagId);
									long relItemTagId = insertRelItemTagStatement
											.executeInsert();
									insertRelItemTagStatement.clearBindings();
								}
							}
						}

					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					statement.clearBindings();
				}
			}

			mDbAdapter.setTransactionSuccessful();

		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		} finally {
			mDbAdapter.endTransaction();
		}
	}
}
